﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


//这个类会涉及到 委托,泛型,接口
public static class ListHelper
{
    /// <summary>
    /// 求最大元素
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <typeparam name="Tkey">元素要比较的字段的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="func">取字段的委托</param>
    /// <returns></returns>
    public static T Max<T, Tkey>(IList<T> list, Func<T, Tkey> func)
        where Tkey : IComparable
    {
        T max = list[0];

        for (int i = 1; i < list.Count; i++)
        {
            if (func(list[i]).CompareTo(func(max)) > 0)
            {
                max = list[i];
            }
        }
        return max;

    }

    /// <summary>
    /// 求最小元素
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <typeparam name="Tkey">元素要比较的字段的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="func">取字段的委托</param>
    /// <returns></returns>
    public static T Min<T, Tkey>(IList<T> list, Func<T, Tkey> func)
        where Tkey : IComparable
    {
        T min = list[0];

        for (int i = 1; i < list.Count; i++)
        {
            if (func(list[i]).CompareTo(func(min)) < 0)
            {
                min = list[i];
            }
        }
        return min;
    }

    /// <summary>
    /// 根据条件查找一个
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="condition">条件</param>
    /// <returns></returns>
    public static bool FindOne<T>(IList<T> list, Func<T, bool> condition, out T result)
    {
        for (int i = 0; i < list.Count; i++)
        {
            if (condition(list[i]))
            {
                result = list[i];
                return true;
            }
        }
        result = default(T);
        return false;
    }

    /// <summary>
    /// 根据条件查找多个
    /// 此方法不适用于,基本数值类型,因为没找到会默认返回0
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="condition">条件</param>
    ///  /// <param name="result">存结果的容器</param>
    public static void FindAll<T>(IList<T> list, Func<T, bool> condition, List<T> result)
    {
        if (result.Count > 0)
        {
            result.Clear();
        }

        for (int i = 0; i < list.Count; i++)
        {
            if (condition(list[i]))
            {
                result.Add(list[i]);
            }
        }
    }
    /// <summary>
    ///排序
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <typeparam name="Tkey">要排序字段的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="func">获取排序字段的委托</param>
    public static void Sort<T, Tkey>(IList<T> list, Func<T, Tkey> func) where Tkey : IComparable
    {
        //外层循环控制选择开始的位置
        for (int i = 0; i < list.Count - 1; i++)
        {
            //从i的位置 选一个最小的 (记下他的位置) 和开头的交换
            //假设开头的就是最小的 
            int index = i;
            for (int j = i; j < list.Count; j++)
            {
                if (func(list[j]).CompareTo(func(list[index])) < 0)
                {
                    index = j;
                }
            }
            //程序执行到这里,index一定是最小元素的索引,和开头的交换
            T temp = list[i];
            list[i] = list[index];
            list[index] = temp;
        }
    }

    /// <summary>
    ///排序-倒序
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <typeparam name="Tkey">要排序字段的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="func">获取排序字段的委托</param>
    public static void SortReverse<T, Tkey>(IList<T> list, Func<T, Tkey> func) where Tkey : IComparable
    {
        //外层循环控制选择开始的位置
        for (int i = 0; i < list.Count - 1; i++)
        {
            //从i的位置 选一个最小的 (记下他的位置) 和开头的交换
            //假设开头的就是最小的 
            int index = i;
            for (int j = i; j < list.Count; j++)
            {
                if (func(list[j]).CompareTo(func(list[index])) > 0)
                {
                    index = j;
                }
            }
            //程序执行到这里,index一定是最小元素的索引,和开头的交换
            T temp = list[i];
            list[i] = list[index];
            list[index] = temp;
        }
    }
    /// <summary>
    ///多条件排序,内部使用选择排序 ,有调用者指定大小关系
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <typeparam name="Tkey">要排序字段的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="func">交换条件 T1当前遍历元素,T2是最小或最大元素</param>
    // 调用示例:比如先根据学生的年龄排序,在根据身高排
    //       ArrayHelper.SortFreedom(arr1, (curent, min) =>
    //       {
    //    
    //         if (curent.age==min.age)
    //           {
    //               return curent.height<min.height;
    //           }
    //           else
    //           {
    //                    return curent.age < min.age;
    //           }
    //       });
    public static void SortFreedom<T>(IList<T> list, Func<T, T, bool> func)
    {
        //外层循环控制选择开始的位置
        for (int i = 0; i < list.Count - 1; i++)
        {
            //从i的位置 选一个最小的 (记下他的位置) 和开头的交换
            //假设开头的就是最小的 
            int index = i;
            for (int j = i; j < list.Count; j++)
            {
                if (func(list[j], list[index]))
                {
                    index = j;
                }
            }
            //程序执行到这里,index一定是最小元素的索引,和开头的交换
            T temp = list[i];
            list[i] = list[index];
            list[index] = temp;
        }
    }
    /// <summary>
    /// 集合转字符串
    /// </summary>
    /// <typeparam name="T">数组(集合)的类型</typeparam>
    /// <param name="list">数组(集合)</param>
    /// <param name="func">搜集数据的委托</param>
    /// <param name="separator">分隔符</param>
    /// <param name="sb">可以从外部定义StringBuilder</param>
    /// <returns></returns>
    public static string ToString<T>(IList<T> list, Func<T, object> func = null, string separator = "", StringBuilder sb = null)
    {
        if (sb == null)
        {
            sb = new StringBuilder();
        }

        for (int i = 0; i < list.Count; i++)
        {

            if (func == null)
            {
                sb.Append(list[i]);
            }
            else
            {
                sb.Append(func(list[i]));
            }

            if (i < list.Count - 1)
            {
                sb.Append(separator);
            }
        }
        return sb.ToString();
    }

    /// <summary>
    /// 遍历For
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="list"></param>
    /// <param name="action"></param>
    public static void For<T>(IList<T> list, Action<T> action)
    {
        for (int i = 0; i < list.Count; i++)
        {
            action(list[i]);
        }
    }
    /// <summary>
    /// 遍历Feach
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="collection"></param>
    /// <param name="action"></param>
    public static void Foreach<T>(ICollection<T> collection, Action<T> action)
    {
        foreach (var item in collection)
        {
            action(item);
        }
    }
}
